package module.map.nodes
{
	import drongo.desktop.selector.SelectorEvent;
	import drongo.desktop.utils.CollisionsHelp;
	import drongo.model.core.IProperty;
	import drongo.model.events.ModelEvent;
	import drongo.model.propertys.ArrayProperty;
	import drongo.model.values.CollectionValue;

	import flash.display.Stage;
	import flash.events.Event;
	import flash.events.MouseEvent;
	import flash.geom.Point;

	import common.view.FGUIMediator;

	import module.map.Operations;
	import module.map.model.MapModel;
	import module.map.model.ProjectModel;
	import module.map.model.Propertys;
	import module.map.operations.propertys.datas.ArrayPropertyChangeData;
	import module.map.operations.propertys.datas.PropertyChangeData;

	import ui.Map.UI_PointView;
	import drongo.model.propertys.NumberProperty;

	public class PointMeidator extends FGUIMediator
	{
		[Inject]
		public var view:UI_PointView;
		[Inject]
		public var project:ProjectModel;
		private var stage:Stage;
		private var currentMap:MapModel;
		private var node:CollectionValue;
		private var points:ArrayProperty;
		private var point:CollectionValue;

		private var viewStartPoint:Point = new Point();
		private var startPoint:Point = new Point();
		private var endPoint:Point = new Point();

		public function PointMeidator()
		{
			super();
		}

		override public function initialize():void
		{
			super.initialize();
			this.node = this.view.data.node;
			this.points = this.node.Get(Propertys.POINTS) as ArrayProperty;
			this.point = this.view.data.point;
			if (this.point.Get(Propertys.WIDTH) == null)
			{
				this.point.Add(new NumberProperty(Propertys.WIDTH, 100));
			}
			this.stage = this.view.displayObject.stage;
			this.currentMap = project.currentMap;
			this.RefreshView();
			this.AddEvents();
		}

		override public function destroy():void
		{
			super.destroy();
			this.RemoveEvents();
		}

		private function RefreshView():void
		{
			this.view.x = this.point.Get(Propertys.X).GetValue();
			this.view.y = this.point.Get(Propertys.Y).GetValue();
			var index:int = this.points.GetChildIndex(this.point);
			if (index == 0)
			{
				this.view.m_c1.selectedIndex = 0;
			}
			else if (index == this.points.length - 1)
			{
				this.view.m_c1.selectedIndex = 1;
			}
			else
			{
				this.view.m_c1.selectedIndex = 2;
			}
			if (this.currentMap.selector.selectedList.indexOf(this.point) >= 0)
			{
				this.view.m_select.visible = true;
			}
			else
			{
				this.view.m_select.visible = false;
			}
			if (this.node.Get(Propertys.EDIATRO_MODE).GetValue() > 0)
			{
				this.view.addEventListener(MouseEvent.MOUSE_DOWN, this.MouseDownHandler, true);
			}
			else
			{
				this.view.removeEventListener(MouseEvent.MOUSE_DOWN, this.MouseDownHandler);
			}
		}

		private function AddEvents():void
		{
			this.node.addEventListener(ModelEvent.CHILD_VALUE_CHANGED, this.NodePropertyUpdate);

			this.currentMap.selector.addEventListener(SelectorEvent.SELECTLIST_CHANGE, this.SelectorListChanged);

			this.stage.addEventListener(Event.ENTER_FRAME, this.Tick);
		}

		private function RemoveEvents():void
		{
			this.node.removeEventListener(ModelEvent.CHILD_VALUE_CHANGED, this.NodePropertyUpdate);

			this.view.removeEventListener(MouseEvent.MOUSE_DOWN, this.MouseDownHandler, 255);
			this.stage.removeEventListener(MouseEvent.MOUSE_MOVE, this.MouseMoveHandler);
			this.stage.removeEventListener(MouseEvent.MOUSE_UP, this.MouseUpHandler);

			this.currentMap.selector.removeEventListener(SelectorEvent.SELECTLIST_CHANGE, this.SelectorListChanged);

			this.stage.removeEventListener(Event.ENTER_FRAME, this.Tick);
		}

		private function SelectorListChanged(e:SelectorEvent):void
		{
			if (this.currentMap.selector.selectedList.indexOf(this.point) >= 0)
			{
				this.view.m_select.visible = true;
			}
			else
			{
				this.view.m_select.visible = false;
			}
		}

		private function NodePropertyUpdate(e:ModelEvent):void
		{
			var property:IProperty = e.newValue as IProperty;
			if (property.GetKey() == Propertys.EDIATRO_MODE)
			{
				this.RefreshView();
			}
		}

		private function MouseDownHandler(e:MouseEvent):void
		{
			e.stopImmediatePropagation();
			e.stopPropagation();
			this.stage.addEventListener(MouseEvent.MOUSE_MOVE, this.MouseMoveHandler);
			this.stage.addEventListener(MouseEvent.MOUSE_UP, this.MouseUpHandler);

			this.viewStartPoint.x = this.view.x;
			this.viewStartPoint.y = this.view.y;

			this.startPoint.x = this.stage.mouseX;
			this.startPoint.y = this.stage.mouseY;

			if (!e.shiftKey)
			{
				this.currentMap.selector.resetSelectList(false);
			}
			this.currentMap.selector.push(this.point);
		}

		private function MouseMoveHandler(e:MouseEvent):void
		{
			this.endPoint.x = this.stage.mouseX;
			this.endPoint.y = this.stage.mouseY;

			this.view.x = this.viewStartPoint.x + (this.endPoint.x - this.startPoint.x);
			this.view.y = this.viewStartPoint.y + (this.endPoint.y - this.startPoint.y);
		}

		private function MouseUpHandler(e:MouseEvent):void
		{
			e.stopImmediatePropagation();
			e.stopPropagation();
			this.stage.removeEventListener(MouseEvent.MOUSE_MOVE, this.MouseMoveHandler);
			this.stage.removeEventListener(MouseEvent.MOUSE_UP, this.MouseUpHandler);

			this.endPoint.x = this.stage.mouseX;
			this.endPoint.y = this.stage.mouseY;
			if (CollisionsHelp.DistanceDetection(this.startPoint, this.endPoint, 2))
			{
				return;
			}
			this.view.x = this.viewStartPoint.x + (this.endPoint.x - this.startPoint.x);
			this.view.y = this.viewStartPoint.y + (this.endPoint.y - this.startPoint.y);

			var selectList:Array = this.currentMap.selector.selectedList;

			var propertyList:Vector.<PropertyChangeData>;
			var arrayChangeData:ArrayPropertyChangeData;

			// 老的属性
			var oldPropertys:Vector.<ArrayPropertyChangeData> = new Vector.<ArrayPropertyChangeData>();
			var pointData:CollectionValue;

			for each (pointData in selectList)
			{
				propertyList = new Vector.<PropertyChangeData>();
				propertyList.push(
						new PropertyChangeData(Propertys.X, pointData.Get(Propertys.X).GetValue()),
						new PropertyChangeData(Propertys.Y, pointData.Get(Propertys.Y).GetValue())
					);
				arrayChangeData = new ArrayPropertyChangeData(
						Propertys.ID, pointData.Get(Propertys.ID).GetValue(),
						propertyList
					);
				oldPropertys.push(arrayChangeData);
			}
			// 新的属性值
			var newPropertys:Vector.<ArrayPropertyChangeData> = new Vector.<ArrayPropertyChangeData>();
			for each (pointData in selectList)
			{
				propertyList = new Vector.<PropertyChangeData>();
				propertyList.push(
						new PropertyChangeData(Propertys.X, pointData.Get(Propertys.X).GetValue() + (this.endPoint.x - this.startPoint.x)),
						new PropertyChangeData(Propertys.Y, pointData.Get(Propertys.Y).GetValue() + (this.endPoint.y - this.startPoint.y))
					);
				arrayChangeData = new ArrayPropertyChangeData(
						Propertys.ID, pointData.Get(Propertys.ID).GetValue(),
						propertyList
					);
				newPropertys.push(arrayChangeData);
			}
			this.project.undoSystem.executeOperation(Operations.ARRAY_PROPERTYS_CHANGE, {parent: this.points, oldPropertys: oldPropertys, newPropertys: newPropertys});
		}
	}
}